#ifndef CAMERA_H
#define CAMERA_H

#include <windows.h>
#include <xnamath.h>

class Camera
{
public:
	Camera();
	~Camera();

	// Get/Set world camera position.
	XMVECTOR GetPositionXM()const;
	XMFLOAT3 GetPosition()const;
	void SetPosition(float _x, float _y, float _z);
	void SetPosition(const XMFLOAT3& _v);
	
	// Get camera basis vectors.
	XMVECTOR GetRightXM()const;
	XMFLOAT3 GetRight()const;
	XMVECTOR GetUpXM()const;
	XMFLOAT3 GetUp()const;
	XMVECTOR GetLookXM()const;
	XMFLOAT3 GetLook()const;

	// Get frustum properties.
	float GetNearZ()const;
	float GetFarZ()const;
	float GetAspect()const;
	float GetFovY()const;
	float GetFovX()const;

	// Get near and far plane dimensions in view space coordinates.
	float GetNearWindowWidth()const;
	float GetNearWindowHeight()const;
	float GetFarWindowWidth()const;
	float GetFarWindowHeight()const;
	
	// Set frustum.
	void SetLens(float _fovY, float _aspect, float _zn, float _zf);

	// Define camera space via LookAt parameters.
	void LookAt(FXMVECTOR _pos, FXMVECTOR _target, FXMVECTOR _worldUp);
	void LookAt(const XMFLOAT3& _pos, const XMFLOAT3& _target, const XMFLOAT3& _up);

	// Get View/Proj matrices.
	XMMATRIX View()const;
	XMMATRIX Proj()const;
	XMMATRIX ViewProj()const;

	// Strafe/Walk the camera a distance d.
	void Strafe(float _d);
	void Walk(float _d);

	// Rotate the camera.
	void Pitch(float _angle);
	void RotateY(float _angle);

	// After modifying camera position/orientation, call to rebuild the view matrix.
	void UpdateViewMatrix();

private:

	// Camera coordinate system with coordinates relative to world space.
	XMFLOAT3 m_Position;
	XMFLOAT3 m_Right;
	XMFLOAT3 m_Up;
	XMFLOAT3 m_Look;
	float angle;

	// Cache frustum properties.
	float m_NearZ;
	float m_FarZ;
	float m_Aspect;
	float m_FovY;
	float m_NearWindowHeight;
	float m_FarWindowHeight;

	// Cache View/Proj matrices.
	XMFLOAT4X4 m_View;
	XMFLOAT4X4 m_Proj;
};

#endif // CAMERA_H